home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / System7 tools / Frontier / Frontier SDK 2.1 / Toolkits / Applet Toolkit / appletquickdraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-11  |  20.9 KB  |  1,212 lines  |  [TEXT/KAHL]

  1.  
  2. /*© Copyright 1988-1992 UserLand Software, Inc.  All Rights Reserved.*/
  3.  
  4.  
  5. #include <GestaltEqu.h>
  6. #include <Palettes.h>
  7. #include "appletdefs.h"
  8. #include "appletfont.h"
  9. #include "appletquickdraw.h"
  10.  
  11.  
  12. typedef char smalliconbits [32];
  13.  
  14. typedef smalliconbits *ptrsmalliconbits, **hdlsmalliconbits;
  15.  
  16.  
  17. typedef struct tyoffscreen {
  18.  
  19.     GDHandle origdevice;
  20.     
  21.     GrafPtr offptr;
  22.     
  23.     Rect offrect;
  24.     
  25.     boolean flsuccess;
  26.     } tyoffscreen;
  27.  
  28. tyoffscreen bitoffscreen;
  29.  
  30. typedef BitMap *typtrbitmap;
  31.  
  32.  
  33. #define ctpens 5 /*we can remember pens up to 5 levels deep*/
  34.  
  35. short toppens = 0;
  36.  
  37. PenState penstack [ctpens];
  38.  
  39.  
  40. #define ctports 5 /*we can remember ports up to 5 levels deep*/
  41.  
  42. short topport = 0;
  43.  
  44. GrafPtr portstack [ctports];
  45.  
  46.  
  47. #define ctclip 5 /*we can remember clips up to 5 levels deep*/
  48.  
  49. short topclip = 0;
  50.  
  51. Rect clipstack [ctclip];
  52.  
  53.  
  54. #define ctstyle 5 /*we can remember font/size/styles up to 5 levels deep*/
  55.  
  56. short topstyle = 0;
  57.  
  58. struct {short fnum, fsize, fstyle;} stylestack [ctstyle];
  59.  
  60.  
  61. #define ctforecolors 5
  62.  
  63. short topforecolor = 0;
  64.  
  65. RGBColor forecolorstack [ctforecolors];
  66.  
  67.  
  68. #define ctbackcolors 5
  69.  
  70. short topbackcolor = 0;
  71.  
  72. RGBColor backcolorstack [ctbackcolors];
  73.  
  74.  
  75.  
  76.  
  77.  
  78. boolean pushpen () {
  79.     
  80.     if (toppens >= ctpens)
  81.         return (false);
  82.         
  83.     GetPenState (&penstack [toppens++]);
  84.     
  85.     return (true);
  86.     } /*pushpen*/
  87.     
  88.  
  89. boolean poppen () {
  90.     
  91.     if (toppens <= 0)
  92.         return (false);
  93.         
  94.     SetPenState (&penstack [--toppens]);
  95.     
  96.     return (true);
  97.     } /*poppen*/
  98.     
  99.  
  100. boolean pushmacport (p) GrafPtr p; {
  101.     
  102.     if (topport >= ctports) {
  103.         
  104.         DebugStr ((ConstStr255Param)"\ppushmacport: no room on stack");
  105.         
  106.         return (false);
  107.         }
  108.  
  109.     portstack [topport++] = quickdrawglobal (thePort);
  110.     
  111.     if (p != nil)
  112.         SetPort (p);
  113.         
  114.     return (true);
  115.     } /*pushmacport*/
  116.         
  117.  
  118. boolean popmacport () {
  119.     
  120.     if (topport <= 0) {
  121.         
  122.         DebugStr ((ConstStr255Param)"\ppopmacport: nothing on stack");
  123.         
  124.         return (false);
  125.         }
  126.     
  127.     SetPort (portstack [--topport]);
  128.     
  129.     return (true);
  130.     } /*popmacport*/
  131.  
  132.  
  133. boolean pushclip (r) Rect r; {
  134.     
  135.     register RgnHandle rgn;
  136.     
  137.     if (topclip >= ctclip)
  138.         return (false);
  139.     
  140.     GetClip (rgn = NewRgn ());
  141.     
  142.     clipstack [topclip++] = (**rgn).rgnBBox;
  143.     
  144.     DisposeRgn (rgn);
  145.     
  146.     ClipRect (&r);
  147.     
  148.     return (true);
  149.     } /*pushclip*/
  150.         
  151.  
  152. boolean popclip () {
  153.     
  154.     if (topclip <= 0)
  155.         return (false);
  156.     
  157.     ClipRect (&clipstack [--topclip]);
  158.     
  159.     return (true);
  160.     } /*popclip*/
  161.  
  162.  
  163. boolean pushstyle (fnum, fsize, fstyle) short fnum, fsize, fstyle; {
  164.     
  165.     if (topstyle >= ctstyle)
  166.         return (false);
  167.         
  168.     getfontsizestyle (
  169.         &stylestack [topstyle].fnum, 
  170.         
  171.         &stylestack [topstyle].fsize, 
  172.         
  173.         &stylestack [topstyle].fstyle);
  174.     
  175.     topstyle++;
  176.     
  177.     setglobalfontsizestyle (fnum, fsize, fstyle);
  178.     
  179.     return (true);
  180.     } /*pushstyle*/
  181.         
  182.  
  183. boolean popstyle (void) {
  184.     
  185.     if (topstyle <= 0)
  186.         return (false);
  187.     
  188.     topstyle--;
  189.     
  190.     setfontsizestyle (
  191.         stylestack [topstyle].fnum, 
  192.         
  193.         stylestack [topstyle].fsize, 
  194.         
  195.         stylestack [topstyle].fstyle);
  196.         
  197.     return (true);
  198.     } /*popstyle*/
  199.  
  200.  
  201. short getmenubarheight (void) {
  202.     
  203.     return (GetMBarHeight ()); /*call Script Manager routine*/
  204.     } /*getmenubarheight*/
  205.  
  206.  
  207. void setrect (Rect *rset, short top, short left, short bottom, short right) {
  208.     
  209.     register Rect *r = rset;
  210.     
  211.     (*r).top = top;
  212.     
  213.     (*r).left = left;
  214.     
  215.     (*r).bottom = bottom;
  216.     
  217.     (*r).right = right;
  218.     } /*setrect*/
  219.     
  220.     
  221. void localtoglobalrect (Rect *rchanged) {
  222.  
  223.     Point p1, p2;
  224.     Rect r;
  225.     
  226.     r = *rchanged;
  227.     
  228.     p1.h = r.left;
  229.     
  230.     p1.v = r.top;
  231.     
  232.     LocalToGlobal (&p1);
  233.     
  234.     p2.h = r.right;
  235.     
  236.     p2.v = r.bottom;
  237.     
  238.     LocalToGlobal (&p2);
  239.     
  240.     Pt2Rect (p1, p2, &r);
  241.     
  242.     *rchanged = r;
  243.     } /*localtoglobalrect*/
  244.     
  245.     
  246. void eraserect (r) Rect r; {
  247.     
  248.     EraseRect (&r);
  249.     } /*eraserect*/
  250.     
  251.     
  252. void movepento (short h, short v) {
  253.     
  254.     MoveTo (h, v);
  255.     } /*movepento*/
  256.     
  257.     
  258. void pendrawline (short h, short v) {
  259.     
  260.     LineTo (h, v);
  261.     } /*pendrawline*/
  262.     
  263.     
  264. void invalrect (r) Rect r; {
  265.     
  266.     if (r.left >= r.right)
  267.         return;
  268.         
  269.     if (r.top >= r.bottom)
  270.         return;
  271.         
  272.     InvalRect (&r);
  273.     } /*invalrect*/
  274.     
  275.  
  276. boolean emptyrect (Rect r) {
  277.     
  278.     /*
  279.     return true if there are any pixels contained inside the rectangle.
  280.     */
  281.     
  282.     return ((r.top == r.bottom) || (r.left == r.right));
  283.     } /*emptyrect*/
  284.     
  285.     
  286. boolean rectlessthan (Rect r1, Rect r2) {
  287.     
  288.     /*
  289.     return true if r1 is "less than" r2.
  290.     
  291.     we look only at the top-left corners of the rectangles. a rectangle is
  292.     less than the other rectangle if it's above the other guy vertically.
  293.     
  294.     if they're both at the same vertical position, then the guy to the left
  295.     of the other is less than.
  296.     
  297.     this helps us implement a rational sort of tabbing thru objects, we go
  298.     from top to bottom and left to right.
  299.     */
  300.     
  301.     if (r1.top != r2.top) { /*comparison is based on tops*/
  302.         
  303.         return (r1.top < r2.top);
  304.         }
  305.     
  306.     return (r1.left < r2.left);
  307.     } /*rectlessthan*/
  308.     
  309.     
  310. static short absint (short x) {
  311.     
  312.     if (x < 0)
  313.         x = -x;
  314.         
  315.     return (x);
  316.     } /*absint*/
  317.     
  318.     
  319. short pointdist (Point pt1, Point pt2) {
  320.     
  321.     return (absint (pt1.h - pt2.h) + absint (pt1.v - pt2.v));
  322.     } /*pointdist*/
  323.  
  324.  
  325. void centerrect (Rect *rcentered, Rect rcontains) {
  326.     
  327.     /*
  328.     center the first rectangle within the second rectangle.
  329.     */
  330.     
  331.     register short height, width;
  332.     Rect r;
  333.     
  334.     r = *rcentered;
  335.     
  336.     width = r.right - r.left;
  337.     
  338.     r.left = rcontains.left + ((rcontains.right - rcontains.left - width) / 2);
  339.     
  340.     r.right = r.left + width;
  341.     
  342.     height = r.bottom - r.top;
  343.     
  344.     r.top = rcontains.top + ((rcontains.bottom - rcontains.top - height) / 2);
  345.     
  346.     r.bottom = r.top + height;
  347.     
  348.     *rcentered = r;
  349.     } /*centerrect*/
  350.  
  351.  
  352. void dropshadowrect (Rect rorig, short width, boolean flerase) {
  353.     
  354.     /*
  355.     draw a drop-shadow to the right and below the indicated rectangle.  if flerase,
  356.     then we fill the drop shadow area with white.
  357.     */
  358.     
  359.     Rect r = rorig;
  360.     register short h, v;
  361.     register short i;
  362.     
  363.     if (flerase) {
  364.         
  365.         pushpen ();
  366.         
  367.         PenMode (patBic);
  368.         }
  369.         
  370.     for (i = 0; i < width; i++) {
  371.         
  372.         h = r.right + i;
  373.         
  374.         MoveTo (h, r.top + i);
  375.         
  376.         LineTo (h, r.bottom + width - 1);
  377.         
  378.         v = r.bottom + i;
  379.         
  380.         MoveTo (r.left + i, v);
  381.         
  382.         LineTo (r.right + width - 1, v);
  383.         } /*for*/
  384.         
  385.     if (flerase)
  386.         poppen ();
  387.     } /*dropshadowrect*/ 
  388.     
  389.     
  390. void invaldropshadow (Rect r, short width) {
  391.     
  392.     /*
  393.     inval the rectangle and it's drop shadow.
  394.     
  395.     5/6/92 DW: work around IOWA problem when the drop shadow shrinks, there's
  396.     no convenient way to inval the old drop shadow. if you ever decrease the
  397.     drop shadow by more than 5 pixels you'll have to do a complete update.
  398.     */
  399.     
  400.     r.right += width + 5;
  401.     
  402.     r.bottom += width + 5;
  403.     
  404.     InvalRect (&r);
  405.     } /*invaldropshadow*/
  406.     
  407.  
  408. #define gestalttrap         0xA1AD
  409. #define unimplementedtrap    0xA09F
  410.  
  411.  
  412. static boolean gestaltavailable (void) {
  413.  
  414.     long gestaltaddr;
  415.     long unimplementedaddr;
  416.  
  417.     gestaltaddr = NGetTrapAddress (gestalttrap, ToolTrap);
  418.     
  419.     unimplementedaddr = NGetTrapAddress (unimplementedtrap, ToolTrap);
  420.     
  421.     return (unimplementedaddr != gestaltaddr);    
  422.     } /*gestaltavailable*/
  423.     
  424.     
  425. static boolean getgestaltattr (OSType selector, long *response) {
  426.     
  427.     OSErr errcode;
  428.     
  429.     if (!gestaltavailable ())
  430.         return (false);
  431.         
  432.     errcode = Gestalt (selector, response);
  433.     
  434.     return (errcode == noErr);
  435.     } /*getgestaltattr*/
  436.     
  437.     
  438. static short maxdepth (void) {
  439.  
  440.     GDHandle hdldevice;
  441.  
  442.     if (!systemhascolor ())
  443.         return (1);
  444.         
  445.     hdldevice = GetMaxDevice (&quickdrawglobal (screenBits).bounds);
  446.  
  447.     if (hdldevice == nil)
  448.         return (1);
  449.         
  450.     return ((**(**hdldevice).gdPMap).pixelSize);
  451.     } /*maxdepth*/
  452.     
  453.     
  454. boolean colorenabled (void) {
  455.  
  456.     if (!systemhascolor ())
  457.         return (false);
  458.         
  459.     return (maxdepth () > 1);
  460.     } /*colorenabled*/
  461.     
  462.     
  463. static short iscolorport (GrafPtr pport) {
  464.  
  465.     return ((*(CGrafPtr) pport).portVersion < 0);
  466.     } /*iscolorport*/
  467.  
  468.  
  469. static boolean getclut (short resid, CTabHandle *hdlctab) {
  470.     
  471.     Handle hdata;
  472.     
  473.     *hdlctab = nil;
  474.     
  475.     hdata = GetResource ('clut', resid);
  476.     
  477.     if (ResError () != noErr)
  478.         return (false);
  479.     
  480.     *hdlctab = (CTabHandle) hdata;
  481.     
  482.     return (true);
  483.     } /*getclut*/
  484.  
  485.  
  486. static boolean getcolorfromindex (short index, RGBColor *rgb) {
  487.  
  488.     CTabHandle hdlctab;
  489.  
  490.     getclut (128, &hdlctab);
  491.     
  492.     *rgb = (**hdlctab).ctTable [index].rgb;
  493.     } /*getcolorfromindex*/
  494.     
  495.     
  496. boolean pushforecolor (short index) {
  497.     
  498.     RGBColor rgb;
  499.     
  500.     if (colorenabled ()) {
  501.     
  502.         if (topforecolor >= ctforecolors) {
  503.             
  504.             DebugStr ((ConstStr255Param) "\ppushforecolor: no room on stack");
  505.             
  506.             return (false);
  507.             }
  508.     
  509.         GetForeColor (&forecolorstack [topforecolor++]);
  510.         
  511.         getcolorfromindex (index, &rgb);
  512.         
  513.         RGBForeColor (&rgb);
  514.         }
  515.         
  516.     return (true);
  517.     } /*pushforecolor*/
  518.         
  519.  
  520. boolean popforecolor (void) {
  521.     
  522.     if (colorenabled ()) {
  523.     
  524.         if (topforecolor <= 0) {
  525.             
  526.             DebugStr ((ConstStr255Param) "\ppopforecolor: nothing on stack");
  527.             
  528.             return (false);
  529.             }
  530.         
  531.         RGBForeColor (&forecolorstack [--topforecolor]);
  532.         }
  533.     
  534.     return (true);
  535.     } /*popforecolor*/
  536.     
  537.  
  538. boolean pushbackcolor (short index) {
  539.     
  540.     RGBColor rgb;
  541.     
  542.     if (colorenabled ()) {
  543.     
  544.         if (topbackcolor >= ctbackcolors) {
  545.             
  546.             DebugStr ((ConstStr255Param) "\ppushbackcolor: no room on stack");
  547.             
  548.             return (false);
  549.             }
  550.         
  551.         GetBackColor (&backcolorstack [topbackcolor++]);
  552.         
  553.         getcolorfromindex (index, &rgb);
  554.         
  555.         RGBBackColor (&rgb);
  556.         }
  557.         
  558.     return (true);
  559.     } /*pushbackcolor*/
  560.         
  561.  
  562. boolean popbackcolor (void) {
  563.     
  564.     if (colorenabled ()) {
  565.     
  566.         if (topbackcolor <= 0) {
  567.             
  568.             DebugStr ((ConstStr255Param) "\ppopbackcolor: nothing on stack");
  569.             
  570.             return (false);
  571.             }
  572.         
  573.         RGBBackColor (&backcolorstack [--topbackcolor]);
  574.         }
  575.     
  576.     return (true);
  577.     } /*popbackcolor*/
  578.     
  579.     
  580. boolean pushcolors (short foreindex, short backindex) {
  581.     
  582.     pushforecolor (foreindex);
  583.     
  584.     return (pushbackcolor (backindex));
  585.     } /*pushcolors*/
  586.     
  587.     
  588. boolean popcolors (void) {
  589.     
  590.     popforecolor ();
  591.     
  592.     return (popbackcolor ());
  593.     } /*popcolors*/
  594.     
  595.     
  596. boolean getcolorpalette (WindowPtr w) {
  597.  
  598.     CTabHandle hclut;
  599.     PaletteHandle hpalette;
  600.  
  601.     getclut (128, &hclut); 
  602.             
  603.     hpalette = GetPalette (w);
  604.     
  605.     if (hpalette == nil)
  606.         hpalette = NewPalette (32, hclut, pmTolerant, 0x0000);
  607.     else
  608.         CTab2Palette (hclut, hpalette, pmTolerant, 0x0000);
  609.  
  610.     SetPalette (w, hpalette, true);
  611.     
  612.     ActivatePalette (w);
  613.     
  614.     return (true);
  615.     } /*getcolorpalette*/
  616.     
  617.  
  618. static void calcrowbytes (boolean flcolor, CGrafPtr offptr, Rect offrect, long *rowbytes) {
  619.  
  620.     short pixelsize;
  621.     short numpix;
  622.     long offbits;
  623.  
  624.     if (flcolor)
  625.         pixelsize = (**(*offptr).portPixMap).pixelSize;
  626.     else
  627.         pixelsize = 1;
  628.     
  629.     numpix = offrect.right - offrect.left;
  630.     
  631.     offbits = pixelsize * numpix;
  632.  
  633.     *rowbytes = ((offbits + 15) / 16) * 2;
  634.     } /*calcrowbytes*/
  635.     
  636.     
  637. static void optimizerect (Rect *r) {
  638.  
  639.     (*r).left = ((*r).left / 32) * 32;
  640.     
  641.     (*r).right = (((*r).right + 31) / 32) * 32;
  642.     } /*optimizerect*/
  643.     
  644.  
  645. static boolean openpixmap (WindowPtr w, Rect offrect,  Boolean flcopy, tyoffscreen *offscreen) {
  646.  
  647.     Rect rectcopy;
  648.     GDHandle maxdevice;
  649.     long offrowbytes;
  650.     long offsize;
  651.     PixMapHandle temppixmap;
  652.     Ptr tempptr;
  653.     CTabHandle temppmtable;
  654.     short err;
  655.     short i;
  656.     Handle temphandle;
  657.     boolean flcolor;
  658.     typtrbitmap destptr;
  659.  
  660.     (*offscreen).flsuccess = false;
  661.  
  662.     if (!SectRect (&(*w).portRect, &offrect, &rectcopy))
  663.         return (false);
  664.  
  665.     SetPort (w);
  666.                 
  667.     if (flcopy)
  668.         optimizerect (&offrect);
  669.  
  670.     (*offscreen).offrect = offrect;
  671.     
  672.     flcolor = iscolorport (w);
  673.     
  674.     if (flcolor) {
  675.     
  676.         localtoglobalrect (&rectcopy);
  677.     
  678.         maxdevice = GetMaxDevice (&rectcopy);
  679.         
  680.         if (maxdevice == nil)
  681.             return (false);
  682.     
  683.         (*offscreen).origdevice = GetGDevice ();
  684.         
  685.         SetGDevice (maxdevice);
  686.         
  687.         (*offscreen).offptr = (GrafPtr) NewPtr (sizeof (CGrafPort));
  688.         }
  689.     else {
  690.         (*offscreen).offptr = (GrafPtr) NewPtr (sizeof (GrafPort));
  691.         }
  692.     
  693.     if (MemError () != 0) {
  694.     
  695.         /*DebugStr ((ConstStr255Param) "\pMemErr in openpixmap");*/
  696.         
  697.         return (false);
  698.         }
  699.     
  700.     if (flcolor)
  701.         OpenCPort ((CGrafPtr) (*offscreen).offptr);
  702.     else
  703.         OpenPort ((*offscreen).offptr);
  704.     
  705.     calcrowbytes (flcolor, (CGrafPtr) (*offscreen).offptr, offrect, &offrowbytes);
  706.     
  707.     offsize = (long) (offrect.bottom - offrect.top) * offrowbytes;
  708.     
  709.     tempptr = NewPtr (offsize);
  710.     
  711.     if (MemError () != 0) {
  712.  
  713.         /*DebugStr ("\pMemErr in openpixmap");*/
  714.         
  715.         SetPort (w);
  716.         
  717.         if (flcolor)
  718.             CloseCPort ((CGrafPtr) (*offscreen).offptr);
  719.         else
  720.             ClosePort ((*offscreen).offptr);
  721.  
  722.         DisposPtr ((Ptr) (*offscreen).offptr);
  723.         
  724.         return (false);
  725.         }
  726.     
  727.     if (flcolor) {
  728.     
  729.         temphandle = (Handle) (**(**maxdevice).gdPMap).pmTable;
  730.         
  731.         err = HandToHand (&temphandle);
  732.         
  733.         if (err != noErr) {
  734.             
  735.             /*DebugStr ("\pMemErr in openpixmap");*/
  736.         
  737.             SetPort (w);
  738.             
  739.             CloseCPort ((CGrafPtr) (*offscreen).offptr);
  740.         
  741.             DisposPtr ((Ptr) (*offscreen).offptr);
  742.             
  743.             DisposPtr (tempptr);
  744.             
  745.             return (false);
  746.             }
  747.             
  748.         temppmtable = (CTabHandle) temphandle;
  749.     
  750.         temppixmap = (*(CGrafPtr) (*offscreen).offptr).portPixMap;
  751.     
  752.         (**temppixmap).baseAddr = tempptr;
  753.         
  754.         (**temppixmap).rowBytes = offrowbytes + 0x8000;
  755.         
  756.         (**temppixmap).bounds = offrect;
  757.         
  758.         for (i = 0; i <= (**temppmtable).ctSize; i++)
  759.             (**temppmtable).ctTable[i].value = i;
  760.             
  761.         (**temppmtable).ctFlags = (**temppmtable).ctFlags & 0x7FFF;
  762.     
  763.         (**temppixmap).pmTable = temppmtable;
  764.         }
  765.     else {
  766.         (*(*offscreen).offptr).portBits.baseAddr = tempptr;
  767.         
  768.         (*(*offscreen).offptr).portBits.rowBytes = offrowbytes;
  769.  
  770.         (*(*offscreen).offptr).portBits.bounds = offrect;
  771.         }
  772.     
  773.     SetPort ((GrafPtr) (*offscreen).offptr);
  774.     
  775.     if (flcopy) {
  776.     
  777.         if (flcolor)
  778.             destptr = (typtrbitmap) (*(*(CGrafPtr) (*offscreen).offptr).portPixMap);
  779.         else
  780.             destptr = &(*(*offscreen).offptr).portBits;
  781.             
  782.         CopyBits (&(*w).portBits, destptr, &offrect, &offrect, 0, nil);
  783.         }
  784.         
  785.     (*offscreen).flsuccess = true;
  786.     
  787.     return (true);
  788.     } /*openpixmap*/
  789.     
  790.     
  791. static void displaypixmap (WindowPtr w, tyoffscreen offscreen, Rect displayrect) {
  792.     
  793.     boolean flcolor;
  794.     typtrbitmap sourceptr;
  795.     WindowPtr currentwindow;
  796.     
  797.     if (!offscreen.flsuccess)
  798.         return;
  799.     
  800.     GetPort (¤twindow);
  801.  
  802.     flcolor = iscolorport (currentwindow);
  803.     
  804.     if (flcolor) {
  805.     
  806.         SetGDevice (offscreen.origdevice);
  807.         
  808.         sourceptr = (typtrbitmap) (*(*(CGrafPtr) offscreen.offptr).portPixMap);
  809.         }
  810.     else
  811.         sourceptr = &(*offscreen.offptr).portBits;
  812.  
  813.     CopyBits (sourceptr, &(*currentwindow).portBits, &offscreen.offrect, &displayrect, 0, nil);
  814.     } /*displaypixmap*/
  815.     
  816.     
  817. static void dispospixmap (WindowPtr w, tyoffscreen offscreen) {
  818.  
  819.     PixMapHandle temppixmap;
  820.     boolean flcolor;
  821.     
  822.     if (!offscreen.flsuccess)
  823.         return;
  824.  
  825.     flcolor = iscolorport (w);
  826.     
  827.     if (flcolor) {
  828.     
  829.         temppixmap = (*(CGrafPtr) offscreen.offptr).portPixMap;
  830.     
  831.         DisposHandle ((Handle) (**temppixmap).pmTable);
  832.         
  833.         DisposPtr ((Ptr) (**temppixmap).baseAddr);
  834.     
  835.         CloseCPort ((CGrafPtr) offscreen.offptr);
  836.         }
  837.     else {
  838.         DisposPtr ((Ptr) (*offscreen.offptr).portBits.baseAddr);
  839.         
  840.         ClosePort (offscreen.offptr);
  841.         }
  842.     
  843.     DisposPtr ((Ptr) offscreen.offptr);
  844.     } /*dispospixmap*/
  845.  
  846.  
  847. static void closepixmap (WindowPtr w, tyoffscreen offscreen) {
  848.  
  849.     PixMapHandle temppixmap;
  850.     boolean flcolor;
  851.     typtrbitmap sourceptr;
  852.     
  853.     if (!offscreen.flsuccess)
  854.         return;
  855.  
  856.     SetPort (w);
  857.     
  858.     flcolor = iscolorport (w);
  859.     
  860.     if (flcolor) {
  861.     
  862.         SetGDevice (offscreen.origdevice);
  863.         
  864.         sourceptr = (typtrbitmap) (*(*(CGrafPtr) offscreen.offptr).portPixMap);
  865.         }
  866.     else
  867.         sourceptr = &(*offscreen.offptr).portBits;
  868.  
  869.     CopyBits (sourceptr, &(*w).portBits, &offscreen.offrect, &offscreen.offrect, 0, nil);
  870.     
  871.     if (flcolor) {
  872.     
  873.         temppixmap = (*(CGrafPtr) offscreen.offptr).portPixMap;
  874.     
  875.         DisposHandle ((Handle) (**temppixmap).pmTable);
  876.         
  877.         DisposPtr ((Ptr) (**temppixmap).baseAddr);
  878.     
  879.         CloseCPort ((CGrafPtr) offscreen.offptr);
  880.         }
  881.     else {
  882.         DisposPtr ((Ptr) (*offscreen.offptr).portBits.baseAddr);
  883.         
  884.         ClosePort (offscreen.offptr);
  885.         }
  886.     
  887.     DisposPtr ((Ptr) offscreen.offptr);
  888.     } /*closepixmap*/
  889.     
  890.     
  891. boolean openbitmap (Rect offrect, WindowPtr w) {
  892.     
  893.     return (openpixmap (w, offrect, true, &bitoffscreen));
  894.     } /*openbitmap*/
  895.     
  896.     
  897. void closebitmap (WindowPtr w) {
  898.     
  899.     closepixmap (w, bitoffscreen);
  900.     } /*closebitmap*/
  901.     
  902.     
  903. boolean plotsmallicon (Rect r, short iconlist, short iconnum, boolean flinvert) {
  904.  
  905.     register hdlsmalliconbits hbits;
  906.     register short mode;
  907.     BitMap bmap;
  908.     WindowPtr w;
  909.     
  910.     GetPort (&w);
  911.     
  912.     hbits = (hdlsmalliconbits) GetResource ('SICN', iconlist);
  913.     
  914.     if (hbits == nil) /*failed to load the resource*/  
  915.         return (false);
  916.         
  917.     r.right = r.left + widthsmallicon; /*we only pay attention to the top, left fields of rectangle*/
  918.     
  919.     r.bottom = r.top + heightsmallicon;
  920.         
  921.     bmap.baseAddr = (Ptr) &(*hbits) [iconnum];
  922.     
  923.     bmap.rowBytes = 2;
  924.     
  925.     bmap.bounds.top = bmap.bounds.left = 0; 
  926.     
  927.     bmap.bounds.bottom = r.bottom - r.top; 
  928.     
  929.     bmap.bounds.right = r.right - r.left;
  930.     
  931.     if (flinvert)
  932.         mode = notSrcCopy;
  933.     else 
  934.         mode = srcOr; /*was srcCopy*/
  935.         
  936.     CopyBits (&bmap, &(*w).portBits, &bmap.bounds, &r, mode, nil);
  937.     
  938.     return (true);
  939.     } /*plotsmallicon*/
  940.     
  941.     
  942. void drawicon (Rect r, short bitdepth, Handle hbits) {
  943.     
  944.     if (bitdepth == 1) {
  945.         
  946.         PlotIcon (&r, hbits);
  947.         
  948.         return;
  949.         }
  950.     } /*drawicon*/
  951.  
  952.  
  953. static void constraintorect (Rect *rconstrained, Rect rcontains, boolean flcenter) {
  954.     
  955.     Rect r;
  956.     Rect rcentered;
  957.     short dh = 0;
  958.     short dv = 0;
  959.     
  960.     r = *rconstrained; /*copy into local*/
  961.     
  962.     /*first, limit size to size of screen*/
  963.     
  964.     r.right = min (r.right, r.left + (rcontains.right - rcontains.left));
  965.     
  966.     r.bottom = min (r.bottom, r.top + (rcontains.bottom - rcontains.top));
  967.     
  968.     /*now, if repositioning is necessary, center in that dimension*/
  969.     
  970.     rcentered = r;
  971.     
  972.     centerrect (&rcentered, rcontains);
  973.     
  974.     if (r.left < rcontains.left) {
  975.         
  976.         if (flcenter)
  977.             dh = rcentered.left - r.left;
  978.         else
  979.             dh = rcontains.left - r.left;
  980.         }
  981.     else if (r.right > rcontains.right) {
  982.         
  983.         if (flcenter)
  984.             dh = rcentered.right - r.right;
  985.         else
  986.             dh = rcontains.right - r.right;
  987.         }
  988.     
  989.     if (r.top < rcontains.top) {
  990.         
  991.         if (flcenter)
  992.             dv = rcentered.top - r.top;
  993.         else
  994.             dv = rcontains.top - r.top;
  995.         }
  996.     else if (r.bottom > rcontains.bottom) {
  997.         
  998.         if (flcenter)
  999.             dv = rcentered.bottom - r.bottom;
  1000.         else
  1001.             dv = rcontains.bottom - r.bottom;
  1002.         }
  1003.     
  1004.     OffsetRect (&r, dh, dv);
  1005.     
  1006.     *rconstrained = r; /*copy back to parameter*/
  1007.     } /*constraintorect*/
  1008.  
  1009.  
  1010. void constraintodesktop (Rect *rconstrained) {
  1011.     
  1012.     Rect rdesktop = (**GrayRgn).rgnBBox;
  1013.     
  1014.     InsetRect (&rdesktop, 10, 10);
  1015.     
  1016.     rdesktop.top += doctitlebarheight; /*leave room for a title bar at top of rectangle*/
  1017.     
  1018.     constraintorect (rconstrained, rdesktop, false);
  1019.     } /*constraintodesktop*/
  1020.     
  1021.         
  1022. void ellipsize (bs, width) Str255 bs; short width; {
  1023.  
  1024.     /*
  1025.     if the string fits inside the given number of pixels, fine -- do nothing
  1026.     and return.
  1027.     
  1028.     if not, return a string that does fit, with ellipses representing the 
  1029.     deleted characters.  ellipses are generated by pressing option-semicolon.
  1030.     */
  1031.     
  1032.     register char len;
  1033.     register short newwidth;
  1034.     
  1035.     if ((newwidth = StringWidth (bs)) <= width) /*nothing to do, the string fits*/
  1036.         return;
  1037.     
  1038.     len = bs [0]; /* current length in characters*/
  1039.     
  1040.     width -= CharWidth ('…'); /* subtract width of ellipses*/
  1041.         
  1042.     do { /*until it fits (or we run out of characters)*/
  1043.     
  1044.         newwidth -= CharWidth (bs [len]);
  1045.         
  1046.         --len;
  1047.     } while ((newwidth > width) && (len != 0));
  1048.     
  1049.     ++len; /*make room for the ellipses*/
  1050.     
  1051.     bs [len] = '…'; 
  1052.     
  1053.     bs [0] = (char) len;
  1054.     } /*ellipsize*/
  1055.     
  1056.  
  1057. void centerstring (r, bs) Rect r; bigstring bs; {
  1058.     
  1059.     /*
  1060.     draw the string in the current font, size and style, centered inside
  1061.     the indicated rectangle.
  1062.     */
  1063.     
  1064.     register short lh = globalfontinfo.ascent + globalfontinfo.descent; /*line height*/
  1065.     register short rh = r.bottom - r.top;
  1066.     register short rw = r.right - r.left;
  1067.     register short h, v;
  1068.     
  1069.     ellipsize (bs, rw); /*make sure it fits inside the rectangle, width-wise*/
  1070.     
  1071.     h = r.left + ((rw - StringWidth (bs)) / 2);
  1072.     
  1073.     v = r.top + ((rh - lh) / 2) + globalfontinfo.ascent;
  1074.     
  1075.     MoveTo (h, v);
  1076.     
  1077.     pushclip (r);
  1078.     
  1079.     DrawString (bs);
  1080.     
  1081.     popclip ();
  1082.     } /*centerstring*/
  1083.  
  1084.  
  1085. void centerwindow (w, rscreen) WindowPtr w; Rect rscreen; {
  1086.  
  1087.     short h, v;
  1088.     Rect r;
  1089.     short minv;
  1090.     
  1091.     r = (*w).portRect;
  1092.     
  1093.     h = rscreen.left + (((rscreen.right - rscreen.left) - (r.right - r.left)) / 2);
  1094.     
  1095.     v = rscreen.top + (((rscreen.bottom - rscreen.top) - (r.bottom - r.top)) / 6);
  1096.     
  1097.     minv = getmenubarheight () + doctitlebarheight + 10;
  1098.     
  1099.     if (v < minv)
  1100.         v = minv;
  1101.     
  1102.     MoveWindow (w, h, v, false);
  1103.     } /*centerwindow*/
  1104.  
  1105.  
  1106. void grayrect (r) Rect r; {
  1107.  
  1108.     pushpen ();
  1109.     
  1110.     PenMode (patBic);
  1111.     
  1112.     PenPat (quickdrawglobal (gray));
  1113.     
  1114.     PaintRect (&r);
  1115.     
  1116.     poppen ();
  1117.     } /*grayrect*/
  1118.     
  1119.  
  1120. boolean pointinrect (Point pt, Rect r) {
  1121.     
  1122.     return (PtInRect (pt, &r));
  1123.     } /*pointinrect*/
  1124.  
  1125.  
  1126. void validrect (Rect r) {
  1127.     
  1128.     ValidRect (&r);
  1129.     } /*validrect*/
  1130.     
  1131.     
  1132. void zerorect (Rect *rzero) {
  1133.     
  1134.     register Rect *r = rzero;
  1135.     
  1136.     (*r).top = (*r).left = (*r).bottom = (*r).right = 0;
  1137.     } /*zerorect*/
  1138.  
  1139.     
  1140. boolean pushemptyclip (void) {
  1141.     
  1142.     /*
  1143.     set up the clip region so that no display will occur
  1144.     */
  1145.     
  1146.     Rect r;
  1147.     
  1148.     zerorect (&r);
  1149.     
  1150.     return (pushclip (r));
  1151.     } /*pushemptyclip*/
  1152.  
  1153.  
  1154. void globaltolocalpoint (WindowPtr w, Point *pt) {
  1155.     
  1156.     pushmacport (w);
  1157.     
  1158.     GlobalToLocal (pt);
  1159.     
  1160.     popmacport ();
  1161.     } /*globaltolocalpoint*/
  1162.     
  1163.     
  1164. void localtoglobalpoint (WindowPtr w, Point *pt) {
  1165.     
  1166.     pushmacport (w);
  1167.     
  1168.     LocalToGlobal (pt);
  1169.     
  1170.     popmacport ();
  1171.     } /*localtoglobalpoint*/
  1172.     
  1173.     
  1174. void scrollrect (Rect r, short dh, short dv) {
  1175.     
  1176.     /*
  1177.     a front end for the Macintosh routine that scrolls a rectangle of pixels.
  1178.     */
  1179.     
  1180.     register RgnHandle rgn;
  1181.     
  1182.     rgn = NewRgn ();
  1183.     
  1184.     ScrollRect (&r, dh, dv, rgn);
  1185.     
  1186.     InvalRgn (rgn);
  1187.     
  1188.     DisposeRgn (rgn);
  1189.     } /*scrollrect*/
  1190.  
  1191.  
  1192. boolean equalrects (r1, r2) Rect r1, r2; {
  1193.     
  1194.     return (
  1195.         (r1.top == r2.top) && (r1.left == r2.left) && 
  1196.         
  1197.         (r1.bottom == r2.bottom) && (r1.right == r2.right));
  1198.     } /*equalrects*/
  1199.     
  1200.     
  1201. boolean systemhascolor (void) {
  1202.  
  1203.     long templong;
  1204.     
  1205.     if (!getgestaltattr (gestaltQuickdrawVersion, &templong))
  1206.         return (false);
  1207.     
  1208.     return (templong >= 0x100);
  1209.     } /*systemhascolor*/
  1210.  
  1211.  
  1212.